home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Applications
/
Python 1.3.3
/
Python 133 SRC
/
Extensions
/
img
/
imgppmmodule.c
< prev
next >
Wrap
Text File
|
1995-12-21
|
14KB
|
576 lines
/***********************************************************
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include "Python.h"
#include "import.h"
#include "ppm.h"
/* The image formats we support */
static PyObject *format_rgb, *format_rgb_b2t, *format_choices;
extern PyObject *getimgformat(); /* Get foirmat by name */
/*
** Since PBMPLUS error handling is abysmal (print message, exit),
** there is a modified version that has (slightly) better error
** handling. Contact jack@cwi.nl if you want it. Define PBMNEWERROR
** if you have the modified pbmplus.
**
** If you don't have it the first pbm error will abort you python
** program.
*/
#define PBMNEWERROR
#ifndef PBMNEWERROR
#define PPM_END
#define PPM_START if (0) {
#define PPM_ENDSTART }
#else
#include <setjmp.h>
jmp_buf ppmerrenv;
char ppmerrstr[1000];
#define PPM_END pm_setmsghandler(0); pm_setexithandler(0);
#define PPM_START if ( setjmp(ppmerrenv) != 0 ) { \
PyErr_SetString(errobject, ppmerrstr); \
*ppmerrstr = '\0'; \
PPM_END
#define PPM_ENDSTART return 0; \
} \
pm_setmsghandler(my_pmerr); \
pm_setexithandler(my_pmexit);
static void
my_pmerr(str)
char *str;
{
strncpy(ppmerrstr, str, 999);
}
static void
my_pmexit()
{
longjmp(ppmerrenv, 1);
}
#endif /* PBMNEWERROR */
/* Ppm objects */
typedef struct {
PyObject_HEAD
PyObject *dict; /* Attributes dictionary */
int is_reader; /* TRUE if this is a reader */
char *filename; /* filename of the image file */
FILE *filep;
pixval maxval;
int format;
} ppmobject;
static PyObject *errobject;
staticforward PyTypeObject Ppmtype;
#define is_ppmobject(v) ((v)->ob_type == &Ppmtype)
static char doc_ppm[] = "This object reads/writes PPM files\n"
"The 'width', 'height' and 'format' attributes describe the picture\n"
"For writers, setting 'forceplain' creates an ASCII PPM file.";
/* Routine to easily obtain C data from the dict python data */
int
ppmselfattr(self, name, fmt, ptr, wanterr)
ppmobject *self;
char *name;
char *fmt;
void *ptr;
int wanterr;
{
PyObject *obj;
char errbuf[100];
obj = PyDict_GetItemString(self->dict, name);
if ( obj == NULL ) {
if ( wanterr ) {
sprintf(errbuf, "Required attribute '%s' not set", name);
PyErr_SetString(errobject, errbuf);
return 0;
} else {
PyErr_Clear();
return 0;
}
}
if ( !PyArg_Parse(obj, fmt, ptr) ) {
if ( !wanterr )
PyErr_Clear();
return 0;
}
return 1;
}
/* Routine to easily insert integer into dictionary */
ppmsetintattr(self, name, value)
ppmobject *self;
char *name;
int value;
{
PyObject *obj;
int rv;
obj = PyInt_FromLong(value);
rv = PyDict_SetItemString(self->dict, name, obj);
Py_DECREF(obj);
return rv;
}
static ppmobject *
newppmobject()
{
ppmobject *xp;
xp = PyObject_NEW(ppmobject, &Ppmtype);
if (xp == NULL)
return NULL;
xp->dict = PyDict_New();
xp->filename = NULL;
xp->filep = NULL;
return xp;
}
static int
initppmreader(self, name)
ppmobject *self;
char *name;
{
char *name_copy;
int cols, rows;
pixval old_pbmmaxval;
if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
PyErr_NoMemory();
return 0;
}
strcpy(name_copy, name);
self->filename = name_copy;
self->is_reader = 1;
if ((self->filep = fopen(self->filename, "rb")) == NULL ) {
PyErr_SetFromErrno(PyExc_IOError);
return 0;
}
PPM_START
fclose(self->filep);
self->filep = 0;
return 0;
PPM_ENDSTART
old_pbmmaxval = ppm_pbmmaxval;
ppm_pbmmaxval = 0xff; /* XXXX Correct for rgb/rgb_b2t formats */
ppm_readppminit(self->filep, &cols, &rows, &self->maxval,
&self->format);
ppm_pbmmaxval = old_pbmmaxval;
PPM_END
ppmsetintattr(self, "width", cols);
ppmsetintattr(self, "height", rows);
PyDict_SetItemString(self->dict, "format", format_rgb);
PyDict_SetItemString(self->dict, "format_choices", format_choices);
if ( PyErr_Occurred() )
return 0;
return 1;
}
static int
initppmwriter(self, name)
ppmobject *self;
char *name;
{
char *name_copy;
if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
PyErr_NoMemory();
return 0;
}
strcpy(name_copy, name);
self->filename = name_copy;
self->filep = NULL;
self->is_reader = 0;
PyDict_SetItemString(self->dict, "format", format_rgb);
PyDict_SetItemString(self->dict, "format_choices", format_choices);
if( PyErr_Occurred())
return 0;
return 1;
}
/* Ppm methods */
static void
ppm_dealloc(xp)
ppmobject *xp;
{
Py_XDECREF(xp->dict);
if( xp->filename )
free(xp->filename);
if( xp->filep )
fclose(xp->filep);
PyMem_DEL(xp);
}
static char doc_read[] = "Read the actual data, returns a string";
static PyObject *
ppm_read(self, args)
ppmobject *self;
PyObject *args;
{
int i, w, h, toptobottom, rowlen;
PyObject *rv;
long *datap;
pixel *pixelrow;
pixel ppmpixel;
long rgbpixel;
PyObject *fmt;
if (!PyArg_ParseTuple(args,""))
return NULL;
if (!self->is_reader) {
PyErr_SetString(errobject, "Cannot read() from writer object");
return NULL;
}
/* XXXX Read data and return it */
/* XXXX Get args from self->dict and write the data */
if ( !ppmselfattr(self, "width", "i", &w, 1) ||
!ppmselfattr(self, "height", "i", &h, 1) ||
!ppmselfattr(self, "format", "O", &fmt, 1) )
return NULL;
if ( fmt == format_rgb )
toptobottom = 1;
else if ( fmt == format_rgb_b2t )
toptobottom = 0;
else {
PyErr_SetString(errobject, "Unsupported image format");
return NULL;
}
pixelrow = 0;
rv = 0;
PPM_START
if ( pixelrow )
pbm_freerow(pixelrow);
if ( rv )
Py_DECREF(rv);
return NULL;
PPM_ENDSTART
pixelrow=ppm_allocrow(w);
if ( (rv=PyString_FromStringAndSize(0, w*h*4)) == NULL ) {
pbm_freerow(pixelrow);
return NULL;
}
datap = (long *)PyString_AsString(rv);
if ( toptobottom ) {
rowlen = w;
} else {
rowlen = -w;
datap = datap + w*(h-1);
}
while( h > 0 ) {
ppm_readppmrow(self->filep, pixelrow, w, self->maxval,
self->format);
for(i=0; i<w; i++) {
ppmpixel = pixelrow[i];
rgbpixel = PPM_GETR(ppmpixel);
rgbpixel |= (PPM_GETG(ppmpixel)) << 8;
rgbpixel |= (PPM_GETB(ppmpixel)) << 16;
datap[i] = rgbpixel;
}
datap += rowlen;
h -= 1;
}
PPM_END
pbm_freerow(pixelrow);
return rv;
}
static char doc_write[] = "Write (string) data to the PPM file";
static PyObject *
ppm_write(self, args)
ppmobject *self;
PyObject *args;
{
long *data;
int datalen;
int i, w, h, rowlen;
PyObject *fmt;
int toptobottom;
pixel *pixelrow;
pixel ppmpixel;
long rgbpixel;
int forceplain;
FILE *filep;
if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
return NULL;
if (self->is_reader) {
PyErr_SetString(errobject, "Cannot write() to reader object");
return NULL;
}
/* XXXX Get args from self->dict and write the data */
if ( !ppmselfattr(self, "width", "i", &w, 1) ||
!ppmselfattr(self, "height", "i", &h, 1) ||
!ppmselfattr(self, "format", "O", &fmt, 1) )
return NULL;
if( w*h*4 != datalen ) {
PyErr_SetString(errobject, "Incorrect datasize");
return NULL;
}
forceplain = 0;
ppmselfattr(self, "forceplain", "i", &forceplain, 0);
if ( fmt == format_rgb ) {
toptobottom = 1;
rowlen = w;
} else if ( fmt == format_rgb_b2t ) {
toptobottom = 0;
rowlen = -w;
data = data + w*(h-1);
} else {
PyErr_SetString(errobject, "Unsupported image format");
return NULL;
}
if ((filep = fopen(self->filename, forceplain?"w":"wb")) == NULL) {
PyErr_SetFromErrno(PyExc_IOError);
return 0;
}
#ifdef macintosh
setfiletype(self->filename, '????', 'PPGM');
#endif
pixelrow = 0;
PPM_START
if ( pixelrow )
pbm_freerow(pixelrow);
fclose(filep);
return NULL;
PPM_ENDSTART
pixelrow=ppm_allocrow(w);
ppm_writeppminit(filep, w, h, 0xff, forceplain);
while( h > 0 ) {
for(i=0; i<w; i++) {
rgbpixel = data[i];
PPM_ASSIGN(ppmpixel, rgbpixel&0xff, (rgbpixel>>8) & 0xff,
(rgbpixel>>16)&0xff);
pixelrow[i] = ppmpixel;
}
ppm_writeppmrow(filep, pixelrow, w, 0xff, forceplain);
data += rowlen;
h -= 1;
}
PPM_END
pbm_freerow(pixelrow);
if (fclose(filep) != 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef ppm_methods[] = {
{"read", (PyCFunction)ppm_read, 1, doc_read},
{"write", (PyCFunction)ppm_write, 1, doc_write},
{NULL, NULL} /* sentinel */
};
static PyObject *
ppm_getattr(xp, name)
ppmobject *xp;
char *name;
{
PyObject *v;
if (xp->dict != NULL) {
if ( strcmp(name, "__dict__") == 0 ) {
Py_INCREF(xp->dict);
return xp->dict;
}
if ( strcmp(name, "__doc__") == 0 ) {
return PyString_FromString(doc_ppm);
}
v = PyDict_GetItemString(xp->dict, name);
if (v != NULL) {
Py_INCREF(v);
return v;
}
}
return Py_FindMethod(ppm_methods, (PyObject *)xp, name);
}
static int
ppm_setattr(xp, name, v)
ppmobject *xp;
char *name;
PyObject *v;
{
if (xp->dict == NULL) {
xp->dict = PyDict_New();
if (xp->dict == NULL)
return -1;
}
if (v == NULL) {
int rv = PyDict_DelItemString(xp->dict, name);
if (rv < 0)
PyErr_SetString(PyExc_AttributeError,
"delete non-existing imgppm attribute");
return rv;
}
else
return PyDict_SetItemString(xp->dict, name, v);
}
static PyTypeObject Ppmtype = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"imgppm", /*tp_name*/
sizeof(ppmobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)ppm_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)ppm_getattr, /*tp_getattr*/
(setattrfunc)ppm_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
static char doc_newreader[] =
"Return an object that reads the PPM/PGM/PBM file passed as argument";
static PyObject *
ppm_newreader(self, args)
PyObject *self;
PyObject *args;
{
char *filename;
ppmobject *obj;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
if ((obj = newppmobject()) == NULL)
return NULL;
if ( !initppmreader(obj, filename) ) {
ppm_dealloc(obj);
return NULL;
}
return (PyObject *)obj;
}
static char doc_newwriter[] =
"Return an object that writes the PPM file passed as argument";
static PyObject *
ppm_newwriter(self, args)
PyObject *self;
PyObject *args;
{
char *filename;
ppmobject *obj;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
if ((obj = newppmobject()) == NULL)
return NULL;
if ( !initppmwriter(obj, filename) ) {
ppm_dealloc(obj);
return NULL;
}
return (PyObject *)obj;
}
/* List of functions defined in the module */
static struct PyMethodDef ppm_module_methods[] = {
{"reader", ppm_newreader, 1, doc_newreader},
{"writer", ppm_newwriter, 1, doc_newwriter},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initimgppm) */
static char doc_imgppm[] =
"Module that reads images from PPM/PGM/PBM files and writes to PPM files.";
void
initimgppm()
{
PyObject *m, *d, *x, *formatmodule, *formatdict;
/* Create the module and add the functions */
m = Py_InitModule("imgppm", ppm_module_methods);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
errobject = PyString_FromString("imgppm.error");
PyDict_SetItemString(d, "error", errobject);
x = PyString_FromString(doc_imgppm);
PyDict_SetItemString(d, "__doc__", x);
/* Get supported formats */
if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
Py_FatalError("imgppm depends on imgformat");
if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
Py_FatalError("imgformat has no dict");
format_rgb = PyDict_GetItemString(formatdict,"rgb");
format_rgb_b2t = PyDict_GetItemString(formatdict,"rgb_b2t");
format_choices = Py_BuildValue("(OO)", format_rgb, format_rgb_b2t);
/* Initialize pbmplus */
{
int ppm_argc;
static char *ppm_arglist[] = { "pbmplus", 0};
char **ppm_argv;
ppm_argc = 1;
ppm_argv = ppm_arglist;
PPM_START /* { */
Py_FatalError("pbmplus initialization error");
} /* PPM_ENDSTART won't work here, it has return NULL */
ppm_init(&ppm_argc, ppm_argv);
PPM_END
}
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module imgppm");
}